package gruppe5.dame.client;


import gruppe5.dame.client.gui.Lobby.LobbyGUI;
import gruppe5.dame.client.gui.game.DameGUI;
import gruppe5.dame.client.loginDialog.LoginDialog;
import gruppe5.dame.model.DameModel;
import gruppe5.dame.model.Pawn;
import gruppe5.dame.model.types.DameEventType;
import gruppe5.dame.model.types.DameGameType;
import gruppe5.dame.server.rfc.cRFC;
import gruppe5.dame.server.rfc.iRFCListener;
import gruppe5.dame.server.rfc.objects.cChatMessage;
import gruppe5.dame.server.rfc.objects.cError;
import gruppe5.dame.server.rfc.objects.cGameCreateRequest;
import gruppe5.dame.server.rfc.objects.cGameJoinRequest;
import gruppe5.dame.server.rfc.objects.cGameMove;
import gruppe5.dame.server.rfc.objects.cLobby;
import gruppe5.dame.server.rfc.objects.cLoginRequest;
import gruppe5.dame.server.rfc.objects.cLoginResponse;
import gruppe5.dame.server.rfc.objects.cPackageHeader;
import gruppe5.dame.server.rfc.objects.cPackageHeader.PackageType;
import gruppe5.dame.server.rfc.objects.cSpielfeld;

import java.awt.Component;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.net.Socket;
import java.net.URI;
import java.net.URL;
import java.util.Scanner;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

/**
 * Das Hauptfenster des Client-Programms.
 * @author Sebastian Kramer 
 * @author Martin Eutinger
 * @author Edmond Landry Nenzeko
 *
 */
public class Hauptfenster extends JFrame implements iRFCListener {
	
	/**
	 * generated serial version ID
	 */
	private static final long serialVersionUID = 1L;
	
//	
//	/**
//	 * DameModel
//	 */
//	private DameModel model = new DameModel(DameGameType.SMALL);
	
	/**
	 * Die Menubar die sich oben am Bildschirm befindet.
	 */
	private Menubar menubar = null;
	
	/**
	 * Lobby und Spiel benutzen den selben Chat aus dem Hauptfenster
	 */
	private Chat chat = new Chat(this);
	
	/**
	 * UI Element Lobby
	 */
	private LobbyGUI lobby = new LobbyGUI(this);
	
	/**
	 * UI Element Dame (Spiel)
	 */
	private DameGUI dame = new DameGUI(this);;
	
	private cRFC oRFC = new cRFC();
	
	/**
	 * ausstehende Einladung
	 */
	//TODO wird evtl. nicht gebraucht - ablehnung offener Einladungen bei Spielbeginn
	private Boolean userInvited = false;
	
	/**
	 * Netzwerkkommunikation f�r das Hauptfenster
	 */
	NetzwerkLoginChat netzwerk;
	
	/**
	 * Socket f&uuml;r die Netzwerkkommunikation
	 */
	Socket socket;

	/**
	 * Login Daten speichern
	 */
	private Boolean saveIpName = false;
	
	/**
	 * Spieler ist im Spiel
	 */
	private Boolean inGame = false;

	private String username;

	
	/**
	 * Konstruktor
	 * @param title Der Titel des Hauptfensters
	 */
	public Hauptfenster(String title)
	{
		netzwerk = new NetzwerkLoginChat(this);
		//JOptionPane.showMessageDialog(null, "listener", "CLIENT", JOptionPane.OK_CANCEL_OPTION);
		oRFC.AddListener(this);
		
		
		
		this.setTitle(title);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
//		this.setExtendedState(MAXIMIZED_BOTH);
		
		
		/**
		 * Erzeugung aller Komponenten des Hauptfensters, Anfang.
		 */
		
		this.setJMenuBar(menubar = new Menubar(this));
		
		/**
		 * Erzeugung aller Komponenten des Hauptfensters, Ende.
		 */
		
		
		/**
		 * Look and Feel einstellen. Look and Feel wird an dieser Stelle eingestellt,
		 * da alle Komponenten breits bekannt sind, der LoginDialog aber nocht nicht erzeugt wurde.
		 */
		this.setLookAndFeel(Ressourcen.getLookAndFeel());
		
		this.pack();
		this.setVisible(true);
		
		/**
		 * User muss sich einloggen
		 */
		LoginDialog loginDialog = new LoginDialog(this);
		try{
			FileReader file = new FileReader("LoginData.txt");
		    BufferedReader br = new BufferedReader(file);
			loginDialog.loginData(br.readLine(), br.readLine());
			br.close();
			file.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		loginDialog.setLocationRelativeTo(null);
		this.setSize(900, 675);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
	}

	/**
	 * Einstellen des Look and Feels _lookAndFeel und update der Komponenten des Hauptfensters. 
	 * Standardm��ig wird das System Look and Feel eingestellt.
	 * @param _lookAndFeel Das Look and Feel das eingestellt werden soll.
	 */
	private void setLookAndFeel(String _lookAndFeel) 
	{
		try 
		{
			Ressourcen.setLookAndFeel(_lookAndFeel);
			UIManager.setLookAndFeel(Ressourcen.getLookAndFeel());
			SwingUtilities.updateComponentTreeUI(this);
			SwingUtilities.updateComponentTreeUI(menubar);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		catch (InstantiationException e) {
			e.printStackTrace();
		}
		catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Main-Methode; erzeugt lediglich ein Hauptfenster.
	 * @param args Noch unbenutzt.
	 */
	public static void main(String[] args) 
	{
		new Hauptfenster("Dame");
	
	}

	/**
	 * Gibt das Chat UI Element zur&uuml;ck. Lobby und Spiel benutzen den selben Chat
	 * @return chat
	 */
	public Chat getChat() {
		return chat;
	}

	/**
	 * Wird vom Chat UI Elemet aufgerufen, wenn der Benutzer einen Text senden will.
	 * @param text
	 */
	public void sendChatMessage(String text) {
		netzwerk.sentChat(text);
	}

	
	/**
	 * Benutzer kommt in die Lobby - Lobby UI element anzeigen
	 */
	public void enterLobby() {
		inGame = false;
		this.remove(dame);
		this.add(lobby);
		revalidate();
		update(this.getGraphics());
		lobby.repaint();
	}
	
	/**
	 * Benutzer startet Spiel - Spiel UI element anzeigen
	 */
	public void enterGame() {
		inGame = true;
		this.remove(lobby);
		this.add(dame);
		revalidate();
		update(this.getGraphics());
	}
	
//	/**
//	 * Gibt das DameModel zur&uuml;ck
//	 * @return
//	 */
//	public DameModel getModel() {
//		return model;
//	}
	

	/**
	 * Gibt den Socket zur&uuml;ck
	 * @return Socket
	 */
	public Socket getSocket() {
		return this.socket;
	}
	
	/**
	 * @return Der Benutzername.
	 */
	public String getUsername() { return this.username; }

	/**
	 * Spieler will das Spiel verlassen
	 */
	public void spielVerlassen() {
		if(inGame)
		dame.spielVerlassen();
	}

	/**
	 * Spieler will sich einloggen
	 * @param ip
	 * @param username
	 */
	public void login(String ip, String username) {
		if(saveIpName) {
			try{
				FileWriter file = new FileWriter("LoginData.txt");
			    BufferedWriter br = new BufferedWriter(file);
				br.write(ip + "\n" + username);
				br.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		netzwerk.login(ip, username);
	}

	/**
	 * Socket zur Netzwerkkommunikation dem Hauptfenster &uuml;bergeben
	 * @param socket
	 */
	public void setSocket(Socket socket) {
		this.socket=socket;
		
	}

	/**
	 * Gibt dem Chat eine neue Nachricht
	 * @param text
	 */
	public void addChatText(String text) {
		chat.addText(text);
	}

	/**
	 * Bei erfolgreicher Verbindung weren die Daten gespeichert
	 * @param enable
	 */
	public void saveConnectionData(Boolean enable) {
		this.saveIpName = enable;
		
	}

	/**
	 * Spielz&uuml;ge als Text anzeigen
	 */
	public void spielzuegeAlsText() {
		dame.spielzuegeAlsText();
		
	}
	
	
	public cRFC get_RFC() {
		return oRFC;
	}

	@Override
	public void OnAll_ChatMessageReceived(int arg0, cChatMessage arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void OnAll_ConnectionEstablished(int arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void OnAll_Disconnected(int arg0) {
		// TODO Auto-generated method stub
		JOptionPane.showMessageDialog(null, "DISCONNECT", "CLIENT", JOptionPane.OK_CANCEL_OPTION);
	}

	@Override
	public void OnAll_ErrorReceived(int arg0, cError arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void OnAll_GameCreateRequestReceived(int arg0,
			cGameCreateRequest arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void OnAll_GameJoinRequestReceived(int arg0, cGameJoinRequest arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void OnAll_GameMoveReceived(int arg0, cGameMove arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void OnAll_LobbyReceived(int arg0, cLobby arg1) {
		//JOptionPane.showMessageDialog(null, "LOBBY received", "CLIENT", JOptionPane.OK_CANCEL_OPTION);
		// TODO Auto-generated method stub
		lobby.setUserList(arg1.usernames);
		lobby.setRoomList(arg1.gamenames);
	}

	@Override
	public void OnAll_LoginRequestReceived(int arg0, cLoginRequest arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void OnAll_LoginResponseReceived(int arg0, cLoginResponse arg1) {
		//JOptionPane.showMessageDialog(null, "LOGIN RESPONSE received", "CLIENT", JOptionPane.OK_CANCEL_OPTION);
		// TODO Auto-generated method stub
		if (arg1.responseSuccessful) {
			this.username = arg1.username;
			// login successful
			//JOptionPane.showMessageDialog(null, "login sucessful", "CLIENT", JOptionPane.OK_CANCEL_OPTION);
			//Component invoker = (JComponent)this.getInvoker();
			enterLobby();
		} else {
			// login failed
			System.exit(-1);
		}
	}

	@Override
	public void OnAll_ObjectReceived(int arg0, PackageType arg1,
			cPackageHeader arg2) {
		// TODO Auto-generated method stub
		//JOptionPane.showMessageDialog(null, "OBJECT received", "CLIENT", JOptionPane.OK_CANCEL_OPTION);
	}

	@Override
	public void OnAll_SpielfeldReceived(int arg0, cSpielfeld arg1) {
		// TODO Auto-generated method stub
		if (arg1.eventType == DameEventType.GAME_STARTS) {
			//dame.setGridSize(arg1.gameType.GRID_SIZE);
			dame.setPlayerColor(arg1.playerColor);
			this.enterGame();
		}
		this.dame.updateSpielfeld(arg1.pawns);
		System.out.println(arg1.eventType.toString());
	}

	@Override
	public void OnServer_Listening(int arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void OnServer_NewClient(int arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}
}
